<template>
  <div>
    <vxe-form
      class-name="form-class-name"
      v-bind="formOptions"
      ref="vxeFormRef"
      @submit="submitEvent"
      @reset="resetEvent"
    >
      <!-- 外部插槽 -->
      <template #[slot]="{ data, field }" v-for="slot in slotNames">
        <slot :name="slot" v-bind="{ data, field }"></slot>
      </template>
    </vxe-form>
  </div>
</template>

<script>
import { cloneDeep } from '@/utils'
import { initOptions } from './unit/init'
import defaultOptions from './unit/default-options'
import { treeToArray } from '@/utils'

export default {
  name: 'Yform',
  props: {
    // 表单配置
    options: Object
  },
  data() {
    return {
      formOptions: {},
      slotNames: [],
      isInitData: false
    }
  },
  computed: {
    /**
     * 组件数据初始化函数
     *
     * 通过深拷贝formOptions.data创建独立的数据副本，确保组件内部数据与外部配置数据的解耦
     * 避免因对象引用关系导致的意外数据污染
     *
     * @returns {Object} 返回基于formOptions.data的深拷贝对象，作为组件的初始数据
     */
    data() {
      return cloneDeep(this.formOptions.data)
    }
  },
  watch: {
    options: {
      deep: true,
      immediate: true,
      handler(val) {
        const cloneDeepVal = cloneDeep(val)

        const { items, rules, data, slotNames } = initOptions(cloneDeepVal)

        this.slotNames = slotNames

        const formOptions = {
          ...defaultOptions,
          ...cloneDeepVal,
          items,
          rules,
          data: this.isInitData ? this.formOptions.data : data
        }
        this.isInitData = true

        // 等待插槽渲染完成

        this.$nextTick(() => {
          this.formOptions = formOptions

          this.$nextTick(() => {
            if (this.options.mounted) {
              this.options.mounted({ data: formOptions.data, Yform: this })
            }
            // 添加级联监听
            this.addCascaderListener()
          })
        })
      }
    }
  },
  methods: {
    /**
     * 触发表单项events
     * @param {String} fields 表单项 field
     * @param {Object} eventType 事件类型
     */
    triggerEvents(fields, eventType) {
      const data = this.formOptions.data
      const $form = this.$refs.vxeFormRef
      fields.forEach((field) => {
        this.$refs.vxeFormRef
          .getItemByField(field)
          .itemRender.events[eventType]({ data, $form })
      })
    },
    // 字段验证成功后的回调
    submitEvent({ data }) {
      this.$emit('submit', cloneDeep(data))
    },
    // 重置事件
    resetEvent({ data }) {
      this.$emit('reset', cloneDeep(data))
    },
    // 重置方法
    reset() {
      this.$refs.vxeFormRef.reset()
    },
    // 设置表单值
    setData(data) {
      if (!data || Array.isArray(data)) {
        console.error('setData 方法需要传入数组类型参数')
        return
      }
      this.$nextTick(() => {
        this.$set(this.formOptions, 'data', {
          ...this.formOptions.data,
          ...cloneDeep(data)
        })
      })
    },
    // 重新渲染字段
    flushFields(fields = []) {
      console.log(fields)
      fields.forEach((field) => {
        this.$refs.vxeFormRef.getItemByField(field).visible = false
        this.$nextTick(() => {
          this.$refs.vxeFormRef.getItemByField(field).visible = true
        })
      })
    },
    // 添加级联监听
    addCascaderListener() {
      // 存储监听器用于组件销毁时移除
      this.cascaderWatchers = this.cascaderWatchers || []

      const hasFieldItems = treeToArray(this.options.items).filter(
        (d) => d.field && d.cascader
      )

      hasFieldItems.forEach(({ field, cascader }) => {
        const unwatch = this.$watch(
          // 使用函数确保动态字段正确解析
          () => this.formOptions.data[field],
          {
            deep: true,
            immediate: true,
            handler: function (newVal, oldValue) {
              const targetFields = Array.isArray(cascader)
                ? cascader
                : [cascader]

              // 校验目标字段是否存在
              const validFields = targetFields.filter((f) =>
                Object.prototype.hasOwnProperty.call(this.formOptions.data, f)
              )

              // 刷新有效字段
              this.flushFields(validFields)

              // 判断逻辑：值变化且（新值为空 或 旧值存在）
              if (newVal !== oldValue && (!newVal || oldValue)) {
                validFields.forEach((f) => {
                  this.formOptions.data[f] = ''
                })
              }
            }.bind(this) // 显式绑定 Vue 实例上下文
          }
        )

        this.cascaderWatchers.push(unwatch)
      })
    },
    // 校验
    async submit() {
      const isNotOk = await this.$refs.vxeFormRef.validate()
      if (!isNotOk) {
        this.submitEvent({ data: this.formOptions.data })
      }
    }
  },
  mounted() {},
  // 在组件销毁时移除监听
  beforeDestroy() {
    this.cascaderWatchers?.forEach((unwatch) => unwatch())
    this.cascaderWatchers = null
  }
}
</script>

<style lang="scss">
.form-class-name {
  .vxe-form--item-title {
    align-items: flex-start;
    padding-top: 0.75rem !important;
  }
}
</style>
